/**
    Copyright (c) 2010 yakiimo02
    Distributed under the New BSD License.
    See included license.txt or http://www.yakiimo3d.com/NewBSDLicense.txt
**/

#include "OITShaderCommon.h"

// Fragment And Link Buffer
RWStructuredBuffer< FragmentLink >  FLBuffer        : register( u1 );
// Start Offset Buffer
RWByteAddressBuffer StartOffsetBuffer                : register( u2 );

/**
*/
struct ScenePS_Input
{
    float4 pos        : SV_POSITION;
    float4 color    : COLOR0;
    uint nCoverage    : SV_COVERAGE;                // Bit set according to which samples are covered.
};

/**
    Store fragments into a linked-list buffer.
*/
[earlydepthstencil]
void StoreFragmentsPS( ScenePS_Input input )
{
    uint x = input.pos.x;        // [0,g_nFrameWidth]
    uint y = input.pos.y;        // [0,g_nFrameHeight]

    // Create fragment data.
    uint4 nColor = saturate( input.color ) * 255;
    FragmentLink element;
    element.fragmentData.nColor = (nColor.x) | (nColor.y << 8) | (nColor.z << 16) | (nColor.a << 24);
    // depth in upper 24-bit, coverage in lower 8-bit
    element.fragmentData.nDepthAndCoverage =  ( (uint)(input.pos.z*(16777215.0f))<<8 ) | input.nCoverage;

    // Increment and get current pixel count.
    uint nPixelCount= FLBuffer.IncrementCounter();

    // Read and update Start Offset Buffer.
    uint nIndex = y * g_nFrameWidth + x;
    uint nStartOffsetAddress = 4 * nIndex;
    uint nOldStartOffset;
    
    StartOffsetBuffer.InterlockedExchange(
        nStartOffsetAddress, nPixelCount, nOldStartOffset );

    // Store fragment link.
    element.nNext = nOldStartOffset;
    FLBuffer[ nPixelCount ] = element;
}